package com.mobile.sync.client.Sync.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import com.mobile.sync.client.Sync.HttpConfiguration;
import com.mobile.sync.client.Sync.IHandler;
import com.mobile.sync.client.Sync.ISync;
import com.mobile.sync.client.impl.AbstractBean;
import com.mobile.sync.client.impl.RequestBean;
import com.mobile.sync.client.impl.ResponseBean;

public class HTTPSyncImpl implements ISync {

	private static HTTPSyncImpl httpSyncImpl;
	private HttpClient httpClient;
	private HttpHost httpHost;
	private List<IHandler> parserList = new ArrayList<IHandler>();
	private int connectionTimeOut = 15000;

	public HTTPSyncImpl(HttpConfiguration config) {
		try {
			httpHost = new HttpHost(config.getServerUrl(),
					config.getServerPort());
			HttpParams params = new BasicHttpParams();
			params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
					HttpVersion.HTTP_1_1);
			params.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET,
					HTTP.UTF_8);
			params.setParameter(CoreProtocolPNames.USER_AGENT,
					"Apache-HttpClient/Android");
			params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
					connectionTimeOut);
			params.setParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK,
					false);

			SchemeRegistry schemeRegistry = new SchemeRegistry();
			schemeRegistry.register(new Scheme("http", PlainSocketFactory
					.getSocketFactory(), config.getServerPort()));
			ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(
					params, schemeRegistry);
			httpClient = new DefaultHttpClient(cm, params);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public AbstractBean send(AbstractBean requestBeans) throws Exception {

		RequestBean requestBean = (RequestBean) requestBeans;
		HttpRequestBase httpMethod = null;

		switch (requestBean.getHttpMethod()) {

		case HttpPost:
			HttpPost post = new HttpPost(requestBean.getAuthUri());
			post.addHeader("Content-Type", "text/xml");
			if (null != requestBean.getDataChunk()) {
				ByteArrayEntity binaryEntity = new ByteArrayEntity(
						requestBean.getDataChunk());
				post.setEntity(binaryEntity);
			}
			httpMethod = post;
			break;

		default:
			throw new IllegalArgumentException("Http Method not supported");
		}

		ResponseBean responseBean = new ResponseBean();

		HttpResponse response = httpClient.execute(httpHost, httpMethod);

		for (Header header : response.getAllHeaders()) {
			responseBean.put(header.getName(), header.getValue());
		}
		responseBean.setServerResponseCode(response.getStatusLine()
				.getStatusCode());

		responseBean
				.setDataChunk(EntityUtils.toByteArray(response.getEntity()));

		for (IHandler handler : parserList) {
			handler.handlerResponse(responseBean);
		}

		return responseBean;

	}

	public static HTTPSyncImpl getSyncInstance(HttpConfiguration config) {
		try {

			if (httpSyncImpl == null) {
				httpSyncImpl = new HTTPSyncImpl(config);

			}
			return httpSyncImpl;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void register(IHandler iParser) {
		if (parserList.contains(iParser)) {

		}
		parserList.add(iParser);
	}
}
